/*
 * JSFConsole - Lightweight JSF Application Monitor
 * Copyright (C) 2009  Grzegorz Bugaj
 * http://www.gregbugaj.com
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
package com.gregbugaj.reflector.visitors;

import java.io.File;
import java.io.FileOutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.gregbugaj.jsfconsole.converters.Converter;
import com.gregbugaj.jsfconsole.converters.ConverterRegistry;
import com.gregbugaj.jsfconsole.converters.DateConverter;
import com.gregbugaj.jsfconsole.util.XMLUtil;
import com.gregbugaj.jsfconsole.util.reflection.DefaultReflectionProvider;
import com.gregbugaj.jsfconsole.util.reflection.ReflectionProviderStrategy;
import com.gregbugaj.reflector.cfg.ClassNamingStrategy;
import com.gregbugaj.reflector.cfg.DefaultNamingStrategy;
import com.gregbugaj.reflector.filter.DummyPropertyFilter;
import com.gregbugaj.reflector.filter.PropertyFilterStrategy;
import com.gregbugaj.reflector.producers.BaseNodeProducer;
/**
 * Context class 
 * @author devil
 *
 */
public class JSFDumpContext {
	private Node root;
	private Node parent;

	private Document document;
	private ConverterRegistry converterRegistry;

	private ClassNamingStrategy namingStrategy;
	private PropertyFilterStrategy filterStrategy;
	private ReflectionProviderStrategy reflectionProviderStrategy;


	public ReflectionProviderStrategy getReflectionProviderStrategy() {
		if(reflectionProviderStrategy==null){
			reflectionProviderStrategy=new DefaultReflectionProvider();
		}
		return reflectionProviderStrategy;
	}


	public void setReflectionProviderStrategy(final ReflectionProviderStrategy reflectionProviderStrategy) {
		this.reflectionProviderStrategy = reflectionProviderStrategy;
	}


	public PropertyFilterStrategy getFilterStrategy() {
		if(filterStrategy==null){
			filterStrategy=new DummyPropertyFilter();
		}
		
		return filterStrategy;
	}


	public void setFilterStrategy(final PropertyFilterStrategy filterStrategy) {
		this.filterStrategy = filterStrategy;
	}


	public ClassNamingStrategy getNamingStrategy() {
		if(namingStrategy==null){
			namingStrategy=new DefaultNamingStrategy();
		}
		return namingStrategy;
	}


	public void setNamingStrategy(final ClassNamingStrategy namingStrategy) {
		this.namingStrategy = namingStrategy;
	}



	public Document getDocument() {
		return document;
	}


	public JSFDumpContext() {
		init();
	}

	private void init() {
		document=XMLUtil.newDocument();
		converterRegistry=new ConverterRegistry();
		root = document.createElement("instance");
		document.appendChild(root);
		parent=root;

		//Registering converters
		converterRegistry.register(new DateConverter());

	}


	public void add(final BaseNodeProducer node, boolean setAsParent) {
		Node n=node.getNode();
		parent.appendChild(n);
		parent = n;
	}

	public void add(final BaseNodeProducer node) {
		parent.appendChild(node.getNode());
	}



	/**
	 * Current parent node
	 * @return
	 */
	public Node getParent() {
		return parent;
	}

	/**
	 * Set parent node
	 * @param parent
	 */
	public void setParent(final Node parent) {
		this.parent = parent;
	}

	/**
	 * Root of the document
	 * @return
	 */
	public Node getRoot() {
		return root;
	}

	/**
	 * Print out current state of the context to a stream
	 */
	public void print() {
		TransformerFactory tranFactory = TransformerFactory.newInstance(); 
		Transformer aTransformer;
		try {
			aTransformer = tranFactory.newTransformer();
			Source src = new DOMSource( document ); 
			Result dest = new StreamResult(new FileOutputStream(new File("c:\\temp.xml"))); 
			aTransformer.transform(src, dest); 

		} catch (Exception e) {
			e.printStackTrace();
		} 
	}

	/**
	 * Convert object to a  String using custom Converter
	 * @param value
	 * @return
	 */
	public String convert(Object value) {		
		if(value == null){
			throw new IllegalArgumentException();
		}
		Converter converter=converterRegistry.lookup(value.getClass());		
		return converter.toString(value);
	}


	public void destroy() {
		
	}

}
